home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Framework / Sources / UDragDrop.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  52.7 KB  |  1,727 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UDragDrop.cp 
  3. // Copyright © 1984-96 by Apple Computer, Inc. All rights reserved.
  4. //---------------------------------------------------------------------------------------- 
  5.  
  6. #if qDrag
  7.  
  8. #ifndef __UDRAGDROP__
  9. #include "UDragDrop.h"
  10. #endif
  11.  
  12. // MacApp
  13.  
  14. #ifndef __UAPPLICATION__
  15. //    #include "UApplication.h"
  16. #endif
  17.  
  18. #ifndef __UAPPLEEVENTS__
  19. #include "UAppleEvents.h"
  20. #endif
  21.  
  22. #ifndef __UBUSYCURSOR__
  23. #include "UBusyCursor.h"
  24. #endif
  25.  
  26. #if qContainer
  27.     #ifndef __UCONTAINER__
  28.     #include "UContainer.h"
  29.     #endif
  30. #endif
  31.  
  32. #ifndef __UCOREGLOBALS__
  33. #include "UCoreGlobals.h"
  34. #endif
  35.  
  36. #ifndef __UCOREUTILITIES__
  37. #include "UCoreUtilities.h"
  38. #endif
  39.  
  40. #ifndef __UDISPATCHER__
  41. #include "UDispatcher.h"
  42. #endif
  43.  
  44. #ifndef __UDRAGDROPBEHAVIOR__
  45. #include "UDragDropBehavior.h"
  46. #endif
  47.  
  48. #ifndef __ULIST__
  49. #include "UList.h"
  50. #endif
  51.  
  52. #ifndef __UMACAPPGLOBALS__
  53. #include "UMacAppGlobals.h"
  54. #endif
  55.  
  56. #ifndef __UMACAPPUTILITIES__
  57. #include "UMacAppUtilities.h"
  58. #endif
  59.  
  60. #ifndef __USCROLLER__
  61. #include "UScroller.h"
  62. #endif
  63.  
  64. #ifndef __UUNDO__
  65. #include "UUndo.h"
  66. #endif
  67.  
  68. #ifndef __UVIEW__
  69. #include "UView.h"
  70. #endif
  71.  
  72. #ifndef __UWINDOW__
  73. #include "UWindow.h"
  74. #endif
  75.  
  76. // CALib
  77.  
  78. #if qContainer
  79.     #ifndef _CALIB_
  80.     #include "CALib.h"
  81.     #endif
  82. #endif
  83.  
  84. // Toolbox
  85.  
  86. #if qPowerPC || qModelCFM
  87.     #ifndef __CODEFRAGMENTS__
  88.     #include <CodeFragments.h>
  89.     #endif
  90. #endif
  91.  
  92. #ifndef __ERRORS__
  93. #include <Errors.h>
  94. #endif
  95.  
  96. #ifndef __FOLDERS__
  97. #include <Folders.h>
  98. #endif
  99.  
  100. #if qPowerPC || qModelCFM
  101.     #ifndef __FRAGLOAD__
  102.     #include <FragLoad.h>
  103.     #endif
  104. #endif
  105.  
  106. //========================================================================================
  107. // Globals
  108. //========================================================================================
  109.  
  110. // public globals
  111. TDragDropSession*        TDragDropSession::fgDragDropSession;
  112.  
  113. // private globals
  114. DragTrackingHandlerUPP     TDragDropSession::fDragTrackingHandlerUPP;
  115. DragReceiveHandlerUPP     TDragDropSession::fDragReceiveHandlerUPP;
  116. DragSendDataUPP            TDragDropSession::fDragSendDataUPP;
  117.  
  118. #if qDebug
  119. short TDragFlavorStream::fInstanceCount;    // initialize static refcount of TDragFlavorStreams
  120. #endif // qDebug
  121.  
  122. //----------------------------------------------------------------------------------------
  123. // InitUDragManager
  124. //----------------------------------------------------------------------------------------
  125. #pragma segment MADragNonRes
  126.  
  127. void InitUDragManager()
  128. {
  129.     if (!HasDragManager())    // balk if drag manager isn't present
  130.     {
  131. #if qDebug
  132.         ProgramBreak("InitUDragManager called but Drag Manager isn't present.");
  133. #endif
  134.         return;
  135.     }
  136.         
  137.     TDragDropSession::fgDragDropSession = new TDragDropSession;
  138.     TDragDropSession::fgDragDropSession->IDragDropSession();
  139.     
  140.     // Force MADragRes jump table to be initialized. Necessary for compatibility
  141.     // with AOCE. Subclasses of TDragDropSession MUST make this call.
  142.     InitializeResidentDragSegment();
  143.     
  144.     MA_REGISTER_SIGNATURE(TDragDropBehavior, kDragDropBehavior);
  145. } // InitUDragManager
  146.  
  147. //----------------------------------------------------------------------------------------
  148. // InitializeResidentDragSegment:Force MADragRes jump table to be initialized. 
  149. // Necessary for compatibility with AOCE. Subclasses of TDragDropSession MUST call
  150. // this function once at startup.
  151. //----------------------------------------------------------------------------------------
  152. #pragma segment MADragRes
  153.  
  154. void InitializeResidentDragSegment()
  155. {
  156.     // nothing to do. calling this function forces the segment loader to initialize
  157.     // the MADragRes segment's jump table.
  158.     return;
  159. }
  160.  
  161. //========================================================================================
  162. // CLASS TDragDropSession
  163. //========================================================================================
  164. #undef Inherited
  165. #define Inherited TObject
  166.  
  167. #pragma segment MADragRes
  168. MA_DEFINE_CLASS_M1(TDragDropSession, Inherited);
  169.  
  170. //----------------------------------------------------------------------------------------
  171. // TDragDropSession constructor
  172. //----------------------------------------------------------------------------------------
  173. #pragma segment MADragNonRes
  174.  
  175. TDragDropSession::TDragDropSession()
  176.     : fDropTarget(NULL),
  177.       fDragSource(NULL),
  178.       fScroller(NULL),
  179.       fSourceWindow(NULL),
  180.       fTargetWindow(NULL),
  181.       fDragItemList(NULL),
  182.       fDragReference(0L),
  183.       fDragLeftSourceView(FALSE),
  184.       fTargetIsHilited(FALSE),
  185.       fUserRequestedCopy(FALSE)
  186. {
  187.  
  188. } // TDragDropSession::TDragDropSession
  189.  
  190. //----------------------------------------------------------------------------------------
  191. // TDragDropSession::IDragDropSession
  192. //----------------------------------------------------------------------------------------
  193. #pragma segment MADragNonRes
  194.  
  195. void TDragDropSession::IDragDropSession()
  196. {
  197.     this->IObject();
  198.     
  199.     fDragItemList = new TDragItemList;
  200.     fDragItemList->IDragItemList();
  201.         
  202.     // create universal proc pointers for the callbacks
  203.     if (fDragTrackingHandlerUPP == NULL)
  204.         fDragTrackingHandlerUPP = NewDragTrackingHandlerProc(TDragDropSession::DragTrackingHandlerGlue);
  205.     FailNIL(fDragTrackingHandlerUPP);
  206.     if (fDragReceiveHandlerUPP == NULL)
  207.         fDragReceiveHandlerUPP = NewDragReceiveHandlerProc(TDragDropSession::DragReceiveHandlerGlue);
  208.     FailNIL(fDragReceiveHandlerUPP);
  209.     if (fDragSendDataUPP == NULL)
  210.         fDragSendDataUPP = NewDragSendDataProc(TDragDropSession::DragSendDataProcGlue);
  211.     FailNIL(fDragSendDataUPP);
  212. } // TDragDropSession::IDragDropSession
  213.  
  214. //----------------------------------------------------------------------------------------
  215. // TDragDropSession::~DragDropSession
  216. //----------------------------------------------------------------------------------------
  217. #pragma segment MADragNonRes
  218.  
  219. TDragDropSession::~TDragDropSession()
  220. {
  221.     fDragItemList = (TDragItemList *)FreeIfObject(fDragItemList);
  222. } // TDragDropSession::~DragDropSession
  223.  
  224. //----------------------------------------------------------------------------------------
  225. // TDragDropSession::DragTrackingHandlerGlue
  226. //----------------------------------------------------------------------------------------
  227. #pragma segment MADragRes
  228.  
  229. pascal OSErr TDragDropSession::DragTrackingHandlerGlue(DragTrackingMessage    message,
  230.                                                     WindowRef        theWindowMgrWindow,
  231.                                                     void*            handlerRefCon,
  232.                                                     DragReference    theDragRef)
  233. {
  234. #if qSegments
  235.     // Set and restore A5 for compatibility with AOCE
  236.     long A5RegisterOnEntry = SetCurrentA5();
  237. #endif
  238.     MAVolatileInit(OSErr, err, noErr);
  239.  
  240.     // scoped for destruction of Metrowerks destruction chain before restoring A5
  241.     {
  242.         
  243.         // it is necessary for a failure handler to exist at this level to prevent
  244.         // blowing away the failure handler stack while in drag manager callbacks
  245.         FailInfo fi;
  246.         Try(fi)
  247.         {
  248.             fgDragDropSession->DragTrackingHandler(message, theWindowMgrWindow,
  249.                                                   handlerRefCon, theDragRef);
  250.             fi.Success();
  251.         }
  252.         else // Recover
  253.         {
  254.             err = fi.error;    // don't resignal - we're in a callback
  255.         }
  256.     }
  257. #if qSegments
  258.     SetA5(A5RegisterOnEntry);
  259. #endif
  260.     return err;
  261. } // TDragDropSession::DragTrackingHandlerGlue
  262.  
  263. //----------------------------------------------------------------------------------------
  264. // TDragDropSession::DragReceiveHandlerGlue
  265. //----------------------------------------------------------------------------------------
  266. #pragma segment MADragRes
  267.  
  268. pascal OSErr TDragDropSession::DragReceiveHandlerGlue(WindowRef        theWindowMgrWindow,
  269.                                                     void*            handlerRefCon,
  270.                                                     DragReference    theDragRef)
  271. {
  272. #if qSegments
  273.     // Set and restore A5 for compatibility with AOCE
  274.     long A5RegisterOnEntry = SetCurrentA5();
  275. #endif
  276.     MAVolatileInit(OSErr, err, noErr);
  277.     // scoped for destruction of Metrowerks destruction chain before restoring A5
  278.     {
  279.         // it is necessary for a failure handler to exist at this level to prevent
  280.         // blowing away the failure handler stack while in drag manager callbacks
  281.         FailInfo fi;
  282.         Try(fi)
  283.         {
  284.             err = fgDragDropSession->DragReceiveHandler(theWindowMgrWindow, 
  285.                                                        handlerRefCon, theDragRef);
  286.             fi.Success();
  287.         }
  288.         else // Recover
  289.         {
  290.             err = fi.error; // don't resignal - we're in a callback
  291.         }
  292.     
  293. #if qDebug
  294.         TDragFlavorStream::CheckInstanceCount();    // test the TDragFlavorStream instance count
  295. #endif
  296.     }
  297. #if qSegments
  298.     SetA5(A5RegisterOnEntry);
  299. #endif
  300.     return err;
  301. } // TDragDropSession::DragReceiveHandlerGlue
  302.  
  303. //----------------------------------------------------------------------------------------
  304. // TDragDropSession::DragSendDataProcGlue
  305. //----------------------------------------------------------------------------------------
  306. #pragma segment MADragRes
  307.  
  308. pascal OSErr TDragDropSession::DragSendDataProcGlue(FlavorType        theType,
  309.                                                     void*            dragSendDataRefCon,
  310.                                                     ItemReference    theItemRef,
  311.                                                     DragReference    theDragRef)
  312. {
  313. #if qSegments
  314.     // Set and restore A5 for compatibility with AOCE
  315.     long A5RegisterOnEntry = SetCurrentA5();
  316. #endif
  317.     MAVolatileInit(OSErr, err, noErr);
  318.     
  319.     // scoped for destruction of Metrowerks destruction chain before restoring A5
  320.     {
  321.         
  322.         // it is necessary for a failure handler to exist at this level to prevent
  323.         // blowing away the failure handler stack while in drag manager callbacks
  324.         FailInfo fi;
  325.         Try(fi)
  326.         {
  327.             fgDragDropSession->DragSendDataProc(theType, dragSendDataRefCon, theItemRef,
  328.                                                theDragRef);
  329.             fi.Success();
  330.         }
  331.         else // Recover
  332.         {
  333.             err = fi.error;    // don't resignal
  334.         }
  335.     }
  336. #if qSegments
  337.     SetA5(A5RegisterOnEntry);
  338. #endif
  339.     return err;
  340. } // TDragDropSession::DragSendDataGlue
  341.  
  342. //----------------------------------------------------------------------------------------
  343. // TDragDropSession::DragTrackingHandler
  344. //----------------------------------------------------------------------------------------
  345. #pragma segment MADragNonRes
  346.  
  347. void TDragDropSession::DragTrackingHandler(DragTrackingMessage    message,
  348.                                             WindowRef            /*theWindowMgrWindow*/,
  349.                                             void*                handlerRefCon,
  350.                                             DragReference        theDragRef)
  351. {
  352.     fDragReference = theDragRef;
  353.         
  354.     switch (message)
  355.     {
  356.         case dragTrackingEnterHandler:
  357.             this->HandleEnterHandler();
  358.             break;
  359.             
  360.         case dragTrackingLeaveHandler:
  361.             this->HandleLeaveHandler();
  362.             break;
  363.         
  364.         case dragTrackingEnterWindow:
  365.             this->HandleEnterWindow((TWindow *)handlerRefCon);
  366.             break;
  367.             
  368.         case dragTrackingLeaveWindow:
  369.             this->HandleLeaveWindow();
  370.             break;
  371.             
  372.         case dragTrackingInWindow:
  373.             this->HandleTrackInWindow();
  374.             break;
  375.                         
  376.         default:
  377.             break;
  378.     }
  379.     return;
  380. } // TDragDropSession::DragTrackingHandler
  381.  
  382. //----------------------------------------------------------------------------------------
  383. // TDragDropSession::DragReceiveHandler
  384. //----------------------------------------------------------------------------------------
  385. #pragma segment MADragNonRes
  386.  
  387. OSErr TDragDropSession::DragReceiveHandler(WindowRef /*theWindowMgrWindow*/,
  388.                                            void* /*handlerRefCon*/,
  389.                                            DragReference theDragRef)
  390. {
  391.     CTempDesc    dropLocationDesc;
  392.     TCommand*    sourceCommand = NULL;
  393.     TCommand*    targetCommand = NULL;
  394.     OSErr        returnValue;
  395.     
  396.     if (!fDropTarget)        // if no current target exists, return immediately
  397.         return dragNotAcceptedErr;
  398.     
  399.     if (fDropTarget->DoMakeDropLocationDescriptor(dropLocationDesc))
  400.         SetDropLocation(theDragRef, dropLocationDesc);
  401.         
  402.     CDragItemIterator dragItemIterator(fDragItemList);
  403.     
  404.     if (fDragSource && !this->UserRequestedCopy() && fDragSource->WillDragMove(fDropTarget))
  405.     {
  406.         if (fDragSource == fDropTarget)
  407.             targetCommand = fDragSource->DoMakeDragDropCommand(cDragMove, dragItemIterator);
  408.         else
  409.         {
  410.             sourceCommand = fDragSource->DoMakeDragDropCommand(cDrag, dragItemIterator);
  411.             sourceCommand->fIdentifier = cDragMove;
  412.             
  413.             dragItemIterator.Reset();    // reset the iterator
  414.             targetCommand = fDropTarget->DoMakeDragDropCommand(cDrop, dragItemIterator);
  415.             targetCommand->fIdentifier = cDragMove;
  416.         }
  417.     }
  418.     else
  419.         targetCommand = fDropTarget->DoMakeDragDropCommand(cDrop, dragItemIterator);
  420.         
  421.     if (targetCommand) // should always have a target command
  422.     {
  423.         if (sourceCommand)
  424.         //{
  425.             //    sourceCommand->LinkToSecondary(targetCommand);            // link the commands
  426.             sourceCommand->fContext->PostCommand(sourceCommand);     // source command is primary
  427.         //}
  428.         //else
  429.         
  430.         targetCommand->fContext->PostCommand(targetCommand); // target command is primary
  431.         
  432.         // if this process is in the background, it is possible for
  433.         // it to be sitting in WaitNextEvent with an infinite sleep value.
  434.         // waking the process will cause the command(s) that were just posted
  435.         // to be processed immediately.
  436.         if (!gDispatcher->IsFrontProcess())
  437.             gDispatcher->WakeProcess();
  438.         
  439.         if (!fDragSource)
  440.         {    
  441.             TInvalCursorCommand *cursorCommand = new TInvalCursorCommand;
  442.             cursorCommand->IInvalCursorCommand();
  443.             gDispatcher->PostCommand(cursorCommand);
  444.         }        
  445.  
  446.         returnValue = noErr;
  447.     }
  448.     else
  449.     {
  450.         returnValue = dragNotAcceptedErr;
  451. #if qDebug
  452.         // its an error if a source command was provided without a target
  453.         if (sourceCommand)
  454.         {
  455.             ProgramBreak("###Drag source provided a target, drop target did not.");
  456.             sourceCommand = (TCommand*)FreeIfObject(sourceCommand);
  457.         }
  458. #endif
  459.     }
  460.         
  461.     this->SetDropTarget(NULL);    // allow the view to clean up
  462.     fUserRequestedCopy = FALSE;    // reset user request for copy
  463.     
  464.     return returnValue;
  465. } // TDragDropSession::DragReceiveHandler
  466.  
  467. //----------------------------------------------------------------------------------------
  468. // TDragDropSession::DragSendDataProc
  469. //----------------------------------------------------------------------------------------
  470. #pragma segment MADragNonRes
  471.  
  472. void TDragDropSession::DragSendDataProc(FlavorType        theType,
  473.                                         void*            /*dragSendDataRefCon*/,
  474.                                         ItemReference    theItemRef,
  475.                                         DragReference
  476. #if qDebug
  477.                                                         theDragRef
  478. #endif
  479.                                         )
  480. {
  481.     TDragItem *promisedItem = NULL;
  482.     
  483. #if qDebug
  484.     if (theDragRef != fDragReference)
  485.         ProgramBreak("###DragSendDataProc called with mismatched Drag Reference");
  486. #endif
  487.     
  488.     promisedItem = new TDragItem(theItemRef);
  489.     promisedItem->IDragItem();
  490.     promisedItem->FocusOnFlavor(theType);
  491.     
  492.     fDragSource->DoFulfillPromise(promisedItem);
  493.     
  494.     FreeIfObject(promisedItem);
  495. } // TDragDropSession::DragSendDataProc
  496.  
  497. //----------------------------------------------------------------------------------------
  498. // TDragDropSession::HandleEnterHandler
  499. //----------------------------------------------------------------------------------------
  500. #pragma segment MADragNonRes
  501.  
  502. void TDragDropSession::HandleEnterHandler()
  503. {
  504.     // initialize the flavor list    
  505.     fDragItemList->BuildListFromDrag();
  506.     
  507.     fDropTarget = NULL;
  508.     fTargetWindow = NULL;
  509.     fTargetIsHilited = FALSE;
  510. } // TDragDropSession::HandleEnterHandler
  511.  
  512. //----------------------------------------------------------------------------------------
  513. // TDragDropSession::HandleLeaveHandler
  514. //----------------------------------------------------------------------------------------
  515. #pragma segment MADragNonRes
  516.  
  517. void TDragDropSession::HandleLeaveHandler()
  518. {
  519.     fDragItemList->FreeAll();
  520. } // TDragDropSession::HandleLeaveHandler
  521.  
  522. //----------------------------------------------------------------------------------------
  523. // TDragDropSession::HandleEnterWindow
  524. //----------------------------------------------------------------------------------------
  525. #pragma segment MADragNonRes
  526.  
  527. void TDragDropSession::HandleEnterWindow(TWindow* targetWindow)
  528. {    
  529.     if (gDispatcher->InModalState() && (gDispatcher->GetFrontWindow() != targetWindow))
  530.         return;
  531.     
  532.     CDragItemIterator dragItemIterator(fDragItemList);
  533.     targetWindow->DragEnteredWindow(dragItemIterator);
  534.     
  535.     fTargetWindow = targetWindow;
  536. } // TDragDropSession::HandleEnterWindow
  537.  
  538. //----------------------------------------------------------------------------------------
  539. // TDragDropSession::HandleLeaveWindow
  540. //----------------------------------------------------------------------------------------
  541. #pragma segment MADragNonRes
  542.  
  543. void TDragDropSession::HandleLeaveWindow()
  544. {
  545.     this->SetDropTarget(NULL);        // clear the current drop target
  546.     
  547.     if (fTargetWindow)
  548.     {
  549.         fTargetWindow->DragLeftWindow();    // notify the window
  550.         fTargetWindow = NULL;                // reset data
  551.     }
  552. }
  553.  
  554. //----------------------------------------------------------------------------------------
  555. // TDragDropSession::HandleTrackInWindow
  556. //----------------------------------------------------------------------------------------
  557. #pragma segment MADragNonRes
  558.  
  559. void TDragDropSession::HandleTrackInWindow()
  560. {
  561.     if (fTargetWindow && !this->HandleAutoScroll())
  562.     {
  563.         TView*    newTarget;
  564.         CPoint    theMouse;
  565.         CPoint    pinnedMouse;
  566.         VPoint    localPoint;
  567.  
  568.         GetDragMouse(fDragReference, theMouse, pinnedMouse);
  569.         
  570.         CDragItemIterator dragItemIterator(fDragItemList);
  571.         newTarget = fTargetWindow->MouseToDropTarget(dragItemIterator, pinnedMouse, localPoint);
  572.         
  573.         this->SetDropTarget(newTarget);
  574.  
  575.         if (fDropTarget)
  576.         {
  577.             fDropTarget->Focus();
  578.             fDropTarget->DoDragWithin(localPoint);
  579.         }
  580.     }    
  581. } // TDragDropSession::HandleTrackInWindow
  582.  
  583. //----------------------------------------------------------------------------------------
  584. // TDragDropSession::HandleAutoScroll
  585. //----------------------------------------------------------------------------------------
  586. #pragma segment MADragNonRes
  587.  
  588. Boolean TDragDropSession::HandleAutoScroll()
  589. {
  590.     Boolean    didScroll = FALSE;
  591.  
  592.     if (fScroller && (fTargetWindow == fSourceWindow) 
  593.             && fSourceWindow->IsActive() && fScroller->Focus())
  594.     {
  595.         VPoint        delta;
  596.         CPoint        pinnedMouse;
  597.         CPoint        theMouse;
  598.         
  599.         GetDragMouse(fDragReference, theMouse, pinnedMouse);
  600.         VPoint    mouseInWindow(pinnedMouse);
  601.         fSourceWindow->SuperToLocal(mouseInWindow);
  602.         
  603.         delta = fScroller->GetDragScrollDelta(mouseInWindow);
  604.         if (delta != gZeroPt)
  605.         {
  606.             this->SetDropTarget(NULL);                // clear the drop target
  607.             
  608.             fScroller->ScrollBy(delta, kRedraw);    // scroll and inval
  609.             fScroller->Update();                    // redraw content
  610.             didScroll = TRUE;
  611.         }
  612.     }
  613.     return didScroll;
  614. } // TDragDropSession::HandleAutoScroll
  615.  
  616. //----------------------------------------------------------------------------------------
  617. // TDragDropSession::HandleDragToTrash
  618. //----------------------------------------------------------------------------------------
  619. #pragma segment MADragNonRes
  620.  
  621. Boolean TDragDropSession::HandleDragToTrash()
  622. {
  623.     Boolean draggedToTrash = FALSE;
  624.     
  625.     if (!this->UserRequestedCopy() && this->IsDropLocationFinderTrash())
  626.     {
  627.         CDragItemIterator    dragItemIterator(fDragItemList);
  628.         TCommand            *dragCommand = NULL;
  629.         
  630.         dragCommand = fDragSource->DoMakeDragDropCommand(cDrag, dragItemIterator);
  631.         if (dragCommand)
  632.             dragCommand->fContext->PostCommand(dragCommand);
  633.         
  634.         if (!gDispatcher->IsFrontProcess())
  635.             gDispatcher->WakeProcess();    // time to wake up...
  636.         
  637.         draggedToTrash = TRUE;
  638.     }
  639.     
  640.     return draggedToTrash;
  641. } // TDragDropSession::HandleDragToTrash
  642.  
  643. //----------------------------------------------------------------------------------------
  644. // TDragDropSession::GetGlobalDragMouse
  645. //----------------------------------------------------------------------------------------
  646. #pragma segment MADragNonRes
  647.  
  648. void TDragDropSession::GetGlobalDragMouse(    CPoint&    mouse,
  649.                                             CPoint&    pinnedMouse)
  650. {
  651.     FailOSErr(GetDragMouse(fDragReference, mouse, pinnedMouse));
  652. } // TDragDropSession::GetGlobalDragMouse
  653.  
  654. //----------------------------------------------------------------------------------------
  655. // TDragDropSession::SetGlobalPinnedDragMouse
  656. //----------------------------------------------------------------------------------------
  657. #pragma segment MADragNonRes
  658.  
  659. void TDragDropSession::SetGlobalPinnedDragMouse(CPoint&    pinnedMouse)
  660. {
  661.     FailOSErr(SetDragMouse(fDragReference, pinnedMouse));
  662. } // TDragDropSession::SetGlobalPinnedDragMouse
  663.  
  664. //----------------------------------------------------------------------------------------
  665. // TDragDropSession::SetDropTarget
  666. //----------------------------------------------------------------------------------------
  667. #pragma segment MADragNonRes
  668.  
  669. void TDragDropSession::SetDropTarget(TView *newDropTarget)
  670. {
  671.     // track whether drag has left the source view
  672.     if (!fDragLeftSourceView && (newDropTarget != fDragSource))    
  673.             fDragLeftSourceView = TRUE;
  674.     
  675.     if (fDropTarget != newDropTarget)
  676.     {
  677.         if (fDropTarget)
  678.         {    
  679.             fDropTarget->Focus();
  680.             fDropTarget->DoDragLeave();            // resign the current target
  681.             this->HideDropTargetHilite();        // unhilite the current target
  682.         }
  683.         
  684.         fDropTarget = newDropTarget;
  685.         
  686.         if (fDropTarget)
  687.         {
  688.             fDropTarget->Focus();
  689.             fDropTarget->DoDragEnter();         // target the new target
  690.             this->ShowDropTargetHilite();
  691.         }
  692.     }
  693. } // TDragDropSession::SetDropTarget
  694.  
  695. //----------------------------------------------------------------------------------------
  696. // TDragDropSession::RegisterDroppableWindow
  697. //----------------------------------------------------------------------------------------
  698. #pragma segment MADragNonRes
  699.  
  700. void TDragDropSession::RegisterDroppableWindow(TWindow *        theWindow,
  701.                                                 WindowRef    theWindowMgrWindow)
  702. {
  703.     // register a window with the Drag Manager. 
  704.     
  705. #if qDebug
  706.     if (!HasDragManager())
  707.     {
  708.         ProgramBreak("Window tried to register w/DragSession when drag isn't available.");
  709.         return;
  710.     }
  711. #endif
  712.  
  713.     MAVolatileInit(WindowRef, volatileWindowMgrWindow, theWindowMgrWindow);
  714.     
  715.     FailInfo fi;
  716.     Try(fi)
  717.     {
  718. #if qContainer
  719.         if (gContainerLib)
  720.         {
  721.             FailOSErr(CAInstallTrackingHandler(fDragTrackingHandlerUPP, theWindowMgrWindow, theWindow));
  722.         
  723.             FailOSErr(CAInstallReceiveHandler(fDragReceiveHandlerUPP, theWindowMgrWindow, theWindow));
  724.         }
  725.         else
  726. #endif
  727.         {
  728.             FailOSErr(InstallTrackingHandler(fDragTrackingHandlerUPP, theWindowMgrWindow, 
  729.                                              theWindow));
  730.  
  731.             FailOSErr(InstallReceiveHandler(fDragReceiveHandlerUPP, theWindowMgrWindow,
  732.                                             theWindow));
  733.         }
  734.         fi.Success();
  735.     }
  736.     else // Recover
  737.     {
  738. #if qContainer
  739.         if (gContainerLib)
  740.         {
  741.             CARemoveTrackingHandler(fDragTrackingHandlerUPP, volatileWindowMgrWindow);
  742.             CARemoveReceiveHandler(fDragReceiveHandlerUPP, volatileWindowMgrWindow);
  743.         }
  744.         else
  745. #endif
  746.         {
  747.             RemoveTrackingHandler(fDragTrackingHandlerUPP, volatileWindowMgrWindow);
  748.             RemoveReceiveHandler(fDragReceiveHandlerUPP, volatileWindowMgrWindow);
  749.         }
  750.     }
  751. } // TDragDropSession::RegisterDroppableWindow
  752.  
  753. //----------------------------------------------------------------------------------------
  754. // TDragDropSession::UnregisterDroppableWindow
  755. //----------------------------------------------------------------------------------------
  756. #pragma segment MADragNonRes
  757.  
  758. void TDragDropSession::UnregisterDroppableWindow(WindowRef    theWindowMgrWindow)
  759. {
  760. #if qDebug
  761.     if (!HasDragManager())
  762.     {
  763.         ProgramBreak("Window tried to unregister w/DragSession when drag isn't available.");
  764.         return;
  765.     }
  766. #endif
  767.  
  768. #if qContainer
  769.     if (gContainerLib)
  770.     {
  771.         CARemoveTrackingHandler(fDragTrackingHandlerUPP, theWindowMgrWindow);
  772.         CARemoveReceiveHandler(fDragReceiveHandlerUPP, theWindowMgrWindow);
  773.     }
  774.     else
  775. #endif
  776.     {
  777.         RemoveTrackingHandler(fDragTrackingHandlerUPP, theWindowMgrWindow);
  778.         RemoveReceiveHandler(fDragReceiveHandlerUPP, theWindowMgrWindow);
  779.     }
  780. } // TDragDropSession::UnregisterDroppableWindow
  781.  
  782.  
  783. //----------------------------------------------------------------------------------------
  784. // TDragDropSession::HasDragLeftSenderWindow
  785. //----------------------------------------------------------------------------------------
  786. #pragma segment MADragNonRes
  787.  
  788. Boolean TDragDropSession::HasDragLeftSenderWindow() const
  789. {
  790.     DragAttributes    attributes;
  791.     
  792.     GetDragAttributes(fDragReference, &attributes);
  793.     return ((attributes & dragHasLeftSenderWindow) == dragHasLeftSenderWindow);
  794. } // TDragDropSession::HasDragLeftSenderWindow
  795.  
  796. //----------------------------------------------------------------------------------------
  797. // TDragDropSession::ShowDropTargetHilite
  798. //----------------------------------------------------------------------------------------
  799. #pragma segment MADragNonRes
  800.  
  801. void TDragDropSession::ShowDropTargetHilite()
  802. {    
  803.     if (fDragLeftSourceView && fDropTarget)
  804.     {
  805.         RgnHandle    hiliteRegion;
  806.             
  807.         hiliteRegion = fDropTarget->DoMakeDropHiliteRegion();
  808.         fDropTarget->LocalToWindowRegion(hiliteRegion);    // convert the region to window coords
  809.         fTargetWindow->Focus();
  810.         
  811.         ShowDragHilite(fDragReference, hiliteRegion, TRUE);
  812.         DisposeRgn(hiliteRegion);
  813.         fTargetIsHilited = TRUE;
  814.     }
  815. } // TDragDropSession::ShowDropTargetHilite
  816.  
  817. //----------------------------------------------------------------------------------------
  818. // TDragDropSession::HideDropTargetHilite
  819. //----------------------------------------------------------------------------------------
  820. #pragma segment MADragNonRes
  821.  
  822. void TDragDropSession::HideDropTargetHilite()
  823. {
  824.     if (fTargetIsHilited)
  825.     {
  826.         fTargetWindow->Focus();
  827.         HideDragHilite(fDragReference);
  828.         fTargetIsHilited = FALSE;
  829.     }
  830. } // TDragDropSession::HideDropTarget
  831.  
  832. //----------------------------------------------------------------------------------------
  833. // TDragDropSession::GetItemCount
  834. //----------------------------------------------------------------------------------------
  835. #pragma segment MADragNonRes
  836.  
  837. unsigned short TDragDropSession::GetItemCount()
  838. {
  839.     return fDragItemList->GetSize();
  840. } // TDragDropSession::GetItemCount
  841.  
  842. //----------------------------------------------------------------------------------------
  843. // TDragDropSession::UserIsDragging
  844. //----------------------------------------------------------------------------------------
  845. #pragma segment MADragNonRes
  846.  
  847. Boolean TDragDropSession::UserIsDragging(CPoint& mousePoint)
  848. {
  849.         
  850.     return WaitMouseMoved(mousePoint);
  851. } // TDragDropSession::UserIsDragging
  852.  
  853. //----------------------------------------------------------------------------------------
  854. // TDragDropSession::UserRequestedCopy
  855. //----------------------------------------------------------------------------------------
  856. #pragma segment MADragNonRes
  857.  
  858. Boolean TDragDropSession::UserRequestedCopy()
  859. {
  860.     if (!fUserRequestedCopy && IsOptionKeyDown())
  861.         fUserRequestedCopy = TRUE;
  862.     
  863.     return fUserRequestedCopy;
  864. } // TDragDropSession::UserRequestedCopy
  865.  
  866. //----------------------------------------------------------------------------------------
  867. // TDragDropSession::ClearDrag
  868. //----------------------------------------------------------------------------------------
  869. #pragma segment MADragNonRes
  870.  
  871. void TDragDropSession::ClearDrag()
  872. {
  873.     if (fDragReference)
  874.         DisposeDrag(fDragReference);
  875.  
  876.     fDropTarget = NULL;
  877.     fDragSource = NULL;
  878.     fDragReference = 0;
  879.     fScroller = NULL;
  880.     fSourceWindow = NULL;
  881.     fTargetWindow = NULL;
  882.     fDragItemList->FreeAll();
  883.     fDragReference = 0L;
  884.     fDragLeftSourceView = FALSE;
  885.     fTargetIsHilited = FALSE;
  886.     fUserRequestedCopy = FALSE;
  887. } // TDragDropSession::ClearDrag
  888.  
  889. //----------------------------------------------------------------------------------------
  890. // TDragDropSession::StartDrag
  891. //----------------------------------------------------------------------------------------
  892. #pragma segment MADragNonRes
  893.  
  894. void TDragDropSession::StartDrag(TView*         sourceView,
  895.                                 TToolboxEvent*    event,
  896.                                 RgnHandle        dragRegion)
  897. {
  898.     OSErr    dragErr;
  899.     Boolean oldBusyCursorState;
  900.     
  901.     fDragSource = sourceView;
  902.     
  903.     this->UserRequestedCopy();    // test for copy override
  904.     fScroller = fDragSource->GetScroller(FALSE);
  905.     fSourceWindow = sourceView->GetWindow();
  906.     
  907.     oldBusyCursorState = gDispatcher->ActivateBusyCursor(FALSE);
  908.     
  909.     TUndoHandler::fgUndoHandler->BeginAction();
  910.  
  911. #if qContainer
  912.     if (gContainerLib)
  913.     {
  914.         // ••• I have no idea what the right CACloneKind is to use here
  915.         // ••• It probably is not possible to determine it here
  916.         // ••• We may need to save the CADocumentRef as a field of the drag session
  917.         
  918.         CADocumentRef caDoc = CAGetDragDropDocument(0);
  919.         CADropResult dropResult = CAStartDrag(caDoc, &event->fEventRecords[0], dragRegion);
  920.         if (event->fDoubleEvent)
  921.             dropResult = CAStartDrag(caDoc, &event->fEventRecords[1], dragRegion);
  922.     }
  923.     else
  924. #endif
  925.         dragErr = TrackDrag(fDragReference, &event->fEventRecord, dragRegion);
  926.     
  927.     // Must refocus on the source. Otherwise the port and the source
  928.     // will get out of synch
  929.     sourceView->Focus();
  930.     
  931.     if (dragErr == noErr)
  932.         this->HandleDragToTrash();
  933.     
  934.     TUndoHandler::fgUndoHandler->EndAction();
  935.  
  936.     TInvalCursorCommand *cursorCommand = new TInvalCursorCommand;
  937.     cursorCommand->IInvalCursorCommand();
  938.     gDispatcher->PostCommand(cursorCommand);
  939.     
  940.     gDispatcher->ActivateBusyCursor(oldBusyCursorState);
  941.     
  942.     this->ClearDrag();
  943. } // TDragDropSession::StartDrag
  944.  
  945. //----------------------------------------------------------------------------------------
  946. // TDragDropSession::AddDragItem
  947. //----------------------------------------------------------------------------------------
  948. #pragma segment MADragNonRes
  949.  
  950. TDragItem* TDragDropSession::AddDragItem(ItemReference     theItemRef)
  951. {
  952.     if (fDragItemList->IsEmpty())    // create a new drag manager drag
  953.     {
  954.         FailOSErr(NewDrag(&fDragReference));
  955. #if qContainer
  956.         if (gContainerLib)
  957.         {
  958.             // ••• I have no idea what the right CACloneKind is to use here
  959.             // ••• It probably is not possible to determine it here
  960.             // ••• We may need to save the CADocumentRef as a field of the drag session
  961.             
  962.             CADocumentRef caDoc = CAGetDragDropDocument(theItemRef);
  963.             
  964.             CASetDataSendProc(caDoc, fDragSendDataUPP, NULL);
  965.             FailOSErr(CAError());
  966.         }
  967.         else
  968. #endif
  969.         FailOSErr(SetDragSendProc(fDragReference, fDragSendDataUPP, NULL));
  970.     }
  971.     
  972.     TDragItem *newItem = new TDragItem(theItemRef);
  973.     newItem->IDragItem();
  974.     fDragItemList->InsertElementInOrder(&newItem);
  975.     
  976.     return newItem;
  977. } // TDragDropSession::AddDragItem
  978.  
  979. //----------------------------------------------------------------------------------------
  980. // TDragDropSession::GetDragItemByIndex
  981. //----------------------------------------------------------------------------------------
  982. #pragma segment MADragNonRes
  983.  
  984. TDragItem* TDragDropSession::GetDragItemByIndex(unsigned short index)
  985. {
  986.     TDragItem *indexedItem = (TDragItem *)fDragItemList->At(index);
  987.     indexedItem->SetPosition(0);
  988.     return indexedItem;
  989. } // TDragDropSession::GetDragItemByIndex
  990.  
  991. //----------------------------------------------------------------------------------------
  992. // TDragDropSession::GetDragItemByReference
  993. //----------------------------------------------------------------------------------------
  994. #pragma segment MADragNonRes
  995.  
  996. TDragItem* TDragDropSession::GetDragItemByReference(ItemReference itemReference)
  997. {
  998.     TDragItem *            dragItem = NULL;
  999.     CDragItemIterator     iter(fDragItemList);
  1000.     
  1001.     for (dragItem = iter.FirstDragItem(); iter.More(); dragItem = iter.NextDragItem())
  1002.     {
  1003.         if (dragItem->GetItemReference() == itemReference)
  1004.         {
  1005.             dragItem->SetPosition(0);
  1006.             return dragItem;
  1007.         }
  1008.     }
  1009.     Failure(minErr, 0);
  1010.     return NULL;
  1011. } // TDragDropSession::GetDragItemByReference
  1012.  
  1013. //----------------------------------------------------------------------------------------
  1014. // TDragDropSession::GetDropLocationDescriptor
  1015. //----------------------------------------------------------------------------------------
  1016. #pragma segment MADragNonRes
  1017.  
  1018. void TDragDropSession::GetDropLocationDescriptor(CAEDesc& dropLocationDesc) const
  1019. {
  1020.     FailOSErr(GetDropLocation(fDragReference, dropLocationDesc));
  1021. } // TDragDropSession::GetDropLocationDescriptor
  1022.  
  1023. //----------------------------------------------------------------------------------------
  1024. // TDragDropSession::IsDropLocationFinderTrash
  1025. //----------------------------------------------------------------------------------------
  1026. #pragma segment MADragNonRes
  1027.  
  1028. Boolean TDragDropSession::IsDropLocationFinderTrash() const
  1029. {
  1030.     MAVolatileInit(Boolean, result, FALSE);
  1031.     
  1032.     CTempDesc    dropLocation;
  1033.  
  1034.     if (fDropTarget)
  1035.         return result;
  1036.         
  1037.     FailInfo fi;
  1038.     Try(fi)
  1039.     {
  1040.         FSSpec        dropLocationSpec;
  1041.         CInfoPBRec    cpb;
  1042.         
  1043.         this->GetDropLocationDescriptor(dropLocation);
  1044.         
  1045.         if (!dropLocation.CanCoerceDesc(typeFSS))
  1046.             result = FALSE;
  1047.         else
  1048.         {
  1049.             dropLocation.GetFSSpec(dropLocationSpec);
  1050.             
  1051.             cpb.dirInfo.ioNamePtr = dropLocationSpec.name;    // get destination's info
  1052.             cpb.dirInfo.ioVRefNum = dropLocationSpec.vRefNum;
  1053.             cpb.dirInfo.ioFDirIndex = 0;
  1054.             cpb.dirInfo.ioDrDirID = dropLocationSpec.parID;
  1055.             
  1056.             FailOSErr(PBGetCatInfoSync(&cpb));
  1057.             
  1058.             if ((cpb.dirInfo.ioFlAttrib & (1<<4)) == (1<<4))    // it's a directory
  1059.             {
  1060.                 short    trashVRefNum;
  1061.                 long    trashDirID;
  1062.     
  1063.                 FailOSErr(FindFolder(cpb.dirInfo.ioVRefNum, 
  1064.                     kTrashFolderType, kDontCreateFolder, &trashVRefNum, &trashDirID));
  1065.                     
  1066.                 if (cpb.dirInfo.ioDrDirID == trashDirID)
  1067.                     result = TRUE;
  1068.             }
  1069.         }
  1070.         fi.Success();
  1071.     }
  1072.     else // recover
  1073.     {
  1074.         result = FALSE;
  1075.     }
  1076.     
  1077.     return result;
  1078. } // TDragDropSession::IsDropLocationFinderTrash
  1079.  
  1080. //========================================================================================
  1081. // CLASS TDragItemList
  1082. //========================================================================================
  1083. #undef Inherited
  1084. #define Inherited TList
  1085.  
  1086. #pragma segment MADragNonRes
  1087. MA_DEFINE_CLASS_M1(TDragItemList, Inherited);
  1088.  
  1089. //----------------------------------------------------------------------------------------
  1090. // TDragItemList::TDragItemList
  1091. //----------------------------------------------------------------------------------------
  1092. #pragma segment MADragNonRes
  1093.  
  1094. TDragItemList::TDragItemList()
  1095. {
  1096.  
  1097. } // TDragItemList::TDragItemList
  1098.  
  1099. //----------------------------------------------------------------------------------------
  1100. // TDragItemList::~TDragItemList
  1101. //----------------------------------------------------------------------------------------
  1102. #pragma segment MADragNonRes
  1103.  
  1104. TDragItemList::~TDragItemList()
  1105. {
  1106.  
  1107. } // TDragItemList::~TDragItemList
  1108.  
  1109. //----------------------------------------------------------------------------------------
  1110. // TDragItemList::IDragItemList
  1111. //----------------------------------------------------------------------------------------
  1112. #pragma segment MADragNonRes
  1113.  
  1114. void TDragItemList::IDragItemList()
  1115. {
  1116.     this->IList();
  1117. } // TDragItemList::IDragItemList
  1118.  
  1119. //----------------------------------------------------------------------------------------
  1120. // TDragItemList::BuildListFromDrag
  1121. //----------------------------------------------------------------------------------------
  1122. #pragma segment MADragNonRes
  1123.  
  1124. void TDragItemList::BuildListFromDrag()
  1125. {
  1126.     DragReference     dragReference = TDragDropSession::fgDragDropSession->GetDragReference();
  1127.     unsigned short    itemCount;
  1128.     TDragItem*        dragItem;
  1129.     ItemReference    itemReference;
  1130.     
  1131.     this->FreeAll();
  1132.     
  1133.     FailOSErr(CountDragItems(dragReference, &itemCount));
  1134.     
  1135.     for (unsigned short itemIndex = 1; itemIndex <= itemCount; itemIndex++)
  1136.     {
  1137.         FailOSErr(GetDragItemReferenceNumber(dragReference, itemIndex, &itemReference));
  1138.         dragItem = new TDragItem(itemReference);
  1139.         dragItem->IDragItem();
  1140.         this->InsertElementsBefore(fSize + 1, &dragItem, 1);
  1141.     }
  1142. } // TDragItemList::BuildListFromDrag
  1143.  
  1144. //========================================================================================
  1145. // CLASS TDragItem
  1146. //========================================================================================
  1147. #undef Inherited
  1148. #define Inherited TObject
  1149.  
  1150. #pragma segment MADragNonRes
  1151. MA_DEFINE_CLASS_M1(TDragItem, Inherited);
  1152.  
  1153. //----------------------------------------------------------------------------------------
  1154. // TDragItem::TDragItem : Empty constructor here to make the compiler happy. Callers
  1155. // should use the alternate constructor that takes an ItemReference as an argument.
  1156. //----------------------------------------------------------------------------------------
  1157. #pragma segment MADragNonRes
  1158.  
  1159. TDragItem::TDragItem()
  1160.     : fItemReference(0),
  1161.       fFlavorOffset(0),
  1162.       fFlavorType('\?\?\?\?')
  1163. {
  1164.  
  1165. } // TDragItem::TDragItem
  1166.  
  1167. //----------------------------------------------------------------------------------------
  1168. // TDragItem::TDragItem
  1169. //----------------------------------------------------------------------------------------
  1170. #pragma segment MADragNonRes
  1171.  
  1172. TDragItem::TDragItem(ItemReference itemReference)
  1173.     : fItemReference(itemReference),
  1174.       fFlavorOffset(0),
  1175.       fFlavorType('\?\?\?\?')
  1176. {
  1177.  
  1178. } // TDragItem::TDragItem
  1179.  
  1180. //----------------------------------------------------------------------------------------
  1181. // TDragItem::~TDragItem
  1182. //----------------------------------------------------------------------------------------
  1183. #pragma segment MADragNonRes
  1184.  
  1185. TDragItem::~TDragItem()
  1186. {
  1187.  
  1188. } // TDragItem::~TDragItem
  1189.  
  1190. //----------------------------------------------------------------------------------------
  1191. // TDragItem::IDragItem
  1192. //----------------------------------------------------------------------------------------
  1193. #pragma segment MADragNonRes
  1194.  
  1195. void TDragItem::IDragItem()
  1196. {
  1197.     this->IObject();
  1198. } // TDragItem::IDragItem
  1199.  
  1200. //----------------------------------------------------------------------------------------
  1201. // TDragItem::AddFlavor
  1202. //----------------------------------------------------------------------------------------
  1203. #pragma segment MADragNonRes
  1204.  
  1205. void TDragItem::AddFlavor(     FlavorType        newFlavor,
  1206.                             CFlavorFlags&    flavorFlags,
  1207.                             void*            buffer,
  1208.                             long            count)
  1209. {
  1210.     FailOSErr(AddDragItemFlavor(TDragDropSession::fgDragDropSession->GetDragReference(), fItemReference,
  1211.                                 newFlavor, buffer, count, flavorFlags));
  1212.     this->FocusOnFlavor(newFlavor);
  1213.     fFlavorOffset = count;
  1214. } // TDragItem::AddFlavor
  1215.  
  1216. //----------------------------------------------------------------------------------------
  1217. // TDragItem::PromiseFlavor
  1218. //----------------------------------------------------------------------------------------
  1219. #pragma segment MADragNonRes
  1220.  
  1221. void TDragItem::PromiseFlavor(    FlavorType        newFlavor,
  1222.                                 CFlavorFlags&    flavorFlags)
  1223. {
  1224.     FailOSErr(AddDragItemFlavor(TDragDropSession::fgDragDropSession->GetDragReference(), fItemReference,
  1225.                                     newFlavor, NULL, 0L, flavorFlags));
  1226.     this->FocusOnFlavor(newFlavor);
  1227. } // TDragItem::PromiseFlavor
  1228.  
  1229. //----------------------------------------------------------------------------------------
  1230. // TDragItem::CountFlavors
  1231. //----------------------------------------------------------------------------------------
  1232. #pragma segment MADragNonRes
  1233.  
  1234. unsigned short TDragItem::CountFlavors()
  1235. {
  1236.     unsigned short flavorCount;
  1237.     
  1238.     FailOSErr(CountDragItemFlavors(TDragDropSession::fgDragDropSession->GetDragReference(), 
  1239.                                    fItemReference, &flavorCount));
  1240.     
  1241.     return flavorCount;
  1242. } // TDragItem::CountFlavors
  1243.  
  1244. //----------------------------------------------------------------------------------------
  1245. // TDragItem::FlavorExists
  1246. //----------------------------------------------------------------------------------------
  1247. #pragma segment MADragNonRes
  1248.  
  1249. Boolean TDragItem::FlavorExists(FlavorType requestedFlavor)
  1250. {
  1251.     FlavorFlags flags;
  1252.     
  1253.     if (GetFlavorFlags(TDragDropSession::fgDragDropSession->GetDragReference(), fItemReference,
  1254.                        requestedFlavor, &flags) == noErr)
  1255.         return TRUE;
  1256.     else
  1257.         return FALSE;
  1258. } // TDragItem::FlavorExists
  1259.  
  1260. //----------------------------------------------------------------------------------------
  1261. // TDragItem::FocusOnFlavor
  1262. //----------------------------------------------------------------------------------------
  1263. #pragma segment MADragNonRes
  1264.  
  1265. void TDragItem::FocusOnFlavor(FlavorType focusFlavor)
  1266. {
  1267.     fFlavorOffset = 0;
  1268.     
  1269.     if (this->FlavorExists(focusFlavor))
  1270.         fFlavorType = focusFlavor;
  1271.     else
  1272.         FailOSErr(badDragFlavorErr);
  1273. } // TDragItem::FocusOnFlavor
  1274.  
  1275. //----------------------------------------------------------------------------------------
  1276. // TDragItem::GetPosition
  1277. //----------------------------------------------------------------------------------------
  1278. #pragma segment MADragNonRes
  1279.  
  1280. long TDragItem::GetPosition()
  1281. {
  1282.     return fFlavorOffset;
  1283. } // TDragItem::GetPosition
  1284.  
  1285. //----------------------------------------------------------------------------------------
  1286. // TDragItem::SetPosition
  1287. //----------------------------------------------------------------------------------------
  1288. #pragma segment MADragNonRes
  1289.  
  1290. void TDragItem::SetPosition(long newPosition)
  1291. {
  1292.     fFlavorOffset = newPosition;
  1293. } // TDragItem::SetPosition
  1294.  
  1295. //----------------------------------------------------------------------------------------
  1296. // TDragItem::GetBounds
  1297. //----------------------------------------------------------------------------------------
  1298. #pragma segment MADragNonRes
  1299.  
  1300. CRect TDragItem::GetBounds()
  1301. {
  1302.     CRect    itemBounds;
  1303.     
  1304.     FailOSErr(GetDragItemBounds(TDragDropSession::fgDragDropSession->GetDragReference(),
  1305.                                 fItemReference, itemBounds));
  1306.     
  1307.     return itemBounds;
  1308. } // TDragItem::GetBounds
  1309.  
  1310. //----------------------------------------------------------------------------------------
  1311. // TDragItem::SetBounds
  1312. //----------------------------------------------------------------------------------------
  1313. #pragma segment MADragNonRes
  1314.  
  1315. void TDragItem::SetBounds(CRect& itemBounds)
  1316. {
  1317.     if (itemBounds != gZeroRect)
  1318.         FailOSErr(SetDragItemBounds(TDragDropSession::fgDragDropSession->GetDragReference(),
  1319.                                     fItemReference, itemBounds));
  1320. }  // TDragItem::SetBounds
  1321.  
  1322. //----------------------------------------------------------------------------------------
  1323. // TDragItem::GetSize
  1324. //----------------------------------------------------------------------------------------
  1325. #pragma segment MADragNonRes
  1326.  
  1327. long TDragItem::GetSize()
  1328. {
  1329.     long    dataSize;
  1330.     
  1331.     FailOSErr(GetFlavorDataSize(TDragDropSession::fgDragDropSession->GetDragReference(), 
  1332.                                 fItemReference, fFlavorType, &dataSize));
  1333.  
  1334.     return dataSize;
  1335. } // TDragItem::GetSize
  1336.  
  1337. //----------------------------------------------------------------------------------------
  1338. // TDragItem::GetFlags
  1339. //----------------------------------------------------------------------------------------
  1340. #pragma segment MADragNonRes
  1341.  
  1342. CFlavorFlags TDragItem::GetFlags()
  1343. {
  1344.     CFlavorFlags flags;
  1345.     
  1346.     FailOSErr(GetFlavorFlags(TDragDropSession::fgDragDropSession->GetDragReference(), fItemReference,
  1347.                              fFlavorType, flags));
  1348.             
  1349.     return flags;
  1350. } // TDragItem::GetFlags
  1351.  
  1352. //----------------------------------------------------------------------------------------
  1353. // TDragItem::GetFlavorType
  1354. //----------------------------------------------------------------------------------------
  1355. #pragma segment MADragNonRes
  1356.  
  1357. FlavorType TDragItem::GetFlavorType()
  1358. {
  1359.     return fFlavorType;
  1360. } // TDragItem::GetFlavorType
  1361.  
  1362. //----------------------------------------------------------------------------------------
  1363. // TDragItem::GetData
  1364. //----------------------------------------------------------------------------------------
  1365. #pragma segment MADragNonRes
  1366.  
  1367. void TDragItem::GetData(void*    buffer,
  1368.                         long&    count)
  1369. {
  1370.     FailOSErr(GetFlavorData(TDragDropSession::fgDragDropSession->GetDragReference(), fItemReference,
  1371.                             fFlavorType, buffer, &count, fFlavorOffset));
  1372.     fFlavorOffset += count;
  1373. } // TDragItem::GetData
  1374.  
  1375. //----------------------------------------------------------------------------------------
  1376. // TDragItem::GetDataAsHandle
  1377. //----------------------------------------------------------------------------------------
  1378. #pragma segment MADragNonRes
  1379.  
  1380. Handle TDragItem::GetDataAsHandle()
  1381. {
  1382.     Handle    dataHandle = NULL;
  1383.     
  1384.     TDragFlavorStream *dragFlavorStream = new TDragFlavorStream;
  1385.     dragFlavorStream->IDragFlavorStream(fFlavorType, fItemReference);
  1386.     dragFlavorStream->SetPosition(fFlavorOffset);
  1387.     dataHandle = StreamToHandle(dragFlavorStream);
  1388.     fFlavorOffset = dragFlavorStream->GetPosition();
  1389.     FreeIfObject(dragFlavorStream);
  1390.  
  1391.     return dataHandle;
  1392. } // TDragItem::GetDataAsHandle
  1393.  
  1394. //----------------------------------------------------------------------------------------
  1395. // TDragItem::SetData
  1396. //----------------------------------------------------------------------------------------
  1397. #pragma segment MADragNonRes
  1398.  
  1399. void TDragItem::SetData(void *    buffer,
  1400.                         long    count)
  1401. {
  1402.     FailOSErr(SetDragItemFlavorData(TDragDropSession::fgDragDropSession->GetDragReference(), fItemReference,
  1403.                                     fFlavorType, buffer, count, fFlavorOffset));
  1404.     fFlavorOffset += count;
  1405. } // TDragItem::SetData
  1406.  
  1407. //----------------------------------------------------------------------------------------
  1408. // TDragItem::SetDataFromHandle
  1409. //----------------------------------------------------------------------------------------
  1410. #pragma segment MADragNonRes
  1411.  
  1412. void TDragItem::SetDataFromHandle(Handle    dataHandle)
  1413. {
  1414.     if (!dataHandle)
  1415.         Failure(minErr, 0);
  1416.     
  1417.     MAVolatileInit(SignedByte, savedHandleState, LockHandle(dataHandle));
  1418.     
  1419.     FailInfo fi;
  1420.     Try(fi)
  1421.     {
  1422.         Size dataSize = GetHandleSize(dataHandle);
  1423.         FailMemError();
  1424.         
  1425.         this->SetData(*dataHandle, dataSize);
  1426.         HSetState(dataHandle, savedHandleState);
  1427.         fi.Success();
  1428.     }
  1429.     else // Recover
  1430.     {
  1431.         HSetState(dataHandle, savedHandleState);
  1432.         fi.ReSignal();
  1433.     }
  1434. } // TDragItem::SetDataFromHandle
  1435.  
  1436. //----------------------------------------------------------------------------------------
  1437. // TDragItem::GetDataStream
  1438. //----------------------------------------------------------------------------------------
  1439. #pragma segment MADragNonRes
  1440.  
  1441. TDragFlavorStream* TDragItem::GetDataStream()
  1442. {
  1443.     TDragFlavorStream *flavorStream = new TDragFlavorStream;
  1444.     flavorStream->IDragFlavorStream(fFlavorType, fItemReference);    
  1445.     
  1446.     return flavorStream;
  1447. } // TDragFlavorStream::GetDataStream
  1448.     
  1449.  
  1450. //========================================================================================
  1451. // CLASS TDragFlavorStream
  1452. //========================================================================================
  1453. #undef Inherited
  1454. #define Inherited TStream
  1455.  
  1456. #pragma segment MADragNonRes
  1457. MA_DEFINE_CLASS_M1(TDragFlavorStream, Inherited);
  1458.  
  1459. //----------------------------------------------------------------------------------------
  1460. // TDragFlavorStream::TDragFlavorStream
  1461. //----------------------------------------------------------------------------------------
  1462. #pragma segment MADragNonRes
  1463.  
  1464. TDragFlavorStream::TDragFlavorStream()
  1465.     : fPosition(0),
  1466.       fFlavorType('\?\?\?\?'),
  1467.       fItemReference(0)
  1468. {
  1469. #if qDebug
  1470.     fInstanceCount++;    // increment the instance counter
  1471. #endif
  1472. } // TDragFlavorStream::TDragFlavorStream
  1473.  
  1474. //----------------------------------------------------------------------------------------
  1475. // TDragFlavorStream::IDragFlavorStream:
  1476. //----------------------------------------------------------------------------------------
  1477. #pragma segment MADragNonRes
  1478.  
  1479. void TDragFlavorStream::IDragFlavorStream(FlavorType    theFlavor,
  1480.                                         ItemReference    theReference)
  1481. {
  1482.     fFlavorType = theFlavor;
  1483.     fItemReference = theReference;
  1484.     
  1485.     this->IStream();
  1486. } // TDragFlavorStream::IDragFlavorStream
  1487.  
  1488.  
  1489. //----------------------------------------------------------------------------------------
  1490. // TDragFlavorStream::~TDragFlavorStream
  1491. //----------------------------------------------------------------------------------------
  1492. #pragma segment MADragNonRes
  1493.  
  1494. TDragFlavorStream::~TDragFlavorStream()
  1495. {
  1496. #if qDebug
  1497.     fInstanceCount--;    // decrement the instance counter
  1498. #endif
  1499. } // TDragFlavorStream::~TDragFlavorStream
  1500.  
  1501.  
  1502. #if qDebug
  1503. //----------------------------------------------------------------------------------------
  1504. // TDragFlavorStream::CheckReferenceCount
  1505. //----------------------------------------------------------------------------------------
  1506. #pragma segment MADragNonRes
  1507.  
  1508. void TDragFlavorStream::CheckInstanceCount()
  1509. {
  1510.     // This method is called by TDragSession before returning control to the drag manager
  1511.     // after receiving a drop.  Any existing instances of TDragFlavorStream are about to
  1512.     // become invalid. If a positive instance count exists, a program break is
  1513.     // generated.
  1514.     if (fInstanceCount)
  1515.     {
  1516.         ProgramBreak("###TDragFlavorStream failed instance count check");
  1517.         fInstanceCount = 0;    // reset the count
  1518.     }
  1519. } // TDragFlavorStream::CheckReferenceCount
  1520. #endif // qDebug
  1521.  
  1522.  
  1523. //----------------------------------------------------------------------------------------
  1524. // TDragFlavorStream::GetPosition
  1525. //----------------------------------------------------------------------------------------
  1526. #pragma segment MADragNonRes
  1527.  
  1528. long TDragFlavorStream::GetPosition()
  1529. {
  1530.     return fPosition;
  1531. } // TDragFlavorStream::GetPosition
  1532.  
  1533. //----------------------------------------------------------------------------------------
  1534. // TDragFlavorStream::SetPosition
  1535. //----------------------------------------------------------------------------------------
  1536. #pragma segment MADragNonRes
  1537.  
  1538. void TDragFlavorStream::SetPosition(long newPosition)
  1539. {
  1540.     OSErr    err = noErr;
  1541.     long    dataSize;
  1542.     
  1543.     dataSize = this->GetSize();
  1544.     
  1545.     if (newPosition < 0)                // Same error returned by File Manager
  1546.         FailOSErr(posErr);
  1547.     else if (newPosition > dataSize)    // Hit the end of the stream
  1548.     {
  1549.         newPosition = dataSize;            // Position to end of stream
  1550.         err = eofErr;
  1551.     }
  1552.     
  1553.     fPosition = newPosition;
  1554.     FailOSErr(err);
  1555. } // TDragFlavorStream::SetPosition
  1556.  
  1557. //----------------------------------------------------------------------------------------
  1558. // TDragFlavorStream::GetSize
  1559. //----------------------------------------------------------------------------------------
  1560. #pragma segment MADragNonRes
  1561.  
  1562. long TDragFlavorStream::GetSize()
  1563. {
  1564.     long    dataSize;
  1565.     OSErr    err;
  1566.     
  1567.     err = GetFlavorDataSize(TDragDropSession::fgDragDropSession->GetDragReference(), fItemReference, 
  1568.                             fFlavorType, &dataSize);
  1569.     if (err != noErr)
  1570.         dataSize = 0L;
  1571.  
  1572.     return dataSize;
  1573. } // TDragFlavorStream::GetSize
  1574.  
  1575. //----------------------------------------------------------------------------------------
  1576. // TDragFlavorStream::ReadBytes
  1577. //----------------------------------------------------------------------------------------
  1578. #pragma segment MADragNonRes
  1579.  
  1580. void TDragFlavorStream::ReadBytes(void*    p,
  1581.                                 long    count)
  1582. {
  1583.     if (count < 0)
  1584.         FailOSErr(paramErr);    // Negative count request
  1585.     
  1586.     if (this->GetSize() - fPosition < count)
  1587.         FailOSErr(eofErr);        // about to read past end of stream
  1588.     
  1589.     // read the bytes
  1590.     long bytesRead = count;
  1591.     FailOSErr(GetFlavorData(TDragDropSession::fgDragDropSession->GetDragReference(), fItemReference, 
  1592.                             fFlavorType, p, &bytesRead, fPosition));
  1593.     fPosition += bytesRead;
  1594. } // TDragFlavorStream::ReadBytes
  1595.  
  1596. //----------------------------------------------------------------------------------------
  1597. // TDragFlavorStream::WriteBytes
  1598. //----------------------------------------------------------------------------------------
  1599. #pragma segment MADragNonRes
  1600.  
  1601. void TDragFlavorStream::WriteBytes(const void* p,
  1602.                                     long count)
  1603. {
  1604.     FailOSErr(SetDragItemFlavorData(TDragDropSession::fgDragDropSession->GetDragReference(), fItemReference, 
  1605.                                     fFlavorType, p, count, fPosition));
  1606.     fPosition += count;
  1607. } // TDragFlavorStream::WriteBytes
  1608.  
  1609. //========================================================================================
  1610. // CLASS CDragItemIterator
  1611. //========================================================================================
  1612.  
  1613. //----------------------------------------------------------------------------------------
  1614. // CDragItemIterator::CDragItemIterator
  1615. //----------------------------------------------------------------------------------------
  1616. #pragma segment IteratorRes
  1617.  
  1618. CDragItemIterator::CDragItemIterator(TDragItemList* itsDragItemList,
  1619.                                     Boolean            itsForward)
  1620.     : CArrayIterator(itsDragItemList, itsForward)
  1621. {
  1622.  
  1623. } // CDragItemIterator::CDragItemIterator
  1624.  
  1625. //----------------------------------------------------------------------------------------
  1626. // CDragItemIterator destructor
  1627. //----------------------------------------------------------------------------------------
  1628. #pragma segment IteratorRes
  1629.  
  1630. CDragItemIterator::~CDragItemIterator()
  1631. {
  1632. }
  1633.  
  1634. //----------------------------------------------------------------------------------------
  1635. // CDragItemIterator::CurrentDragItem
  1636. //----------------------------------------------------------------------------------------
  1637. #pragma segment IteratorRes
  1638.  
  1639. TDragItem* CDragItemIterator::CurrentDragItem()
  1640. {
  1641.     if (this->More())
  1642.         return (TDragItem *)((TDragItemList *)fDynamicArray)->At(fCurrentIndex);
  1643.     else
  1644.         return NULL;
  1645. } // CDragItemIterator::CurrentDragItem
  1646.  
  1647. //----------------------------------------------------------------------------------------
  1648. // CDragItemIterator::FirstDragItem
  1649. //----------------------------------------------------------------------------------------
  1650. #pragma segment IteratorRes
  1651.  
  1652. TDragItem* CDragItemIterator::FirstDragItem()
  1653. {
  1654.     this->Reset();
  1655.     if (this->More())
  1656.         return (TDragItem *)((TDragItemList *)fDynamicArray)->At(fCurrentIndex);
  1657.     else
  1658.         return NULL;
  1659. } // CDragItemIterator::FirstDragItem
  1660.  
  1661. //----------------------------------------------------------------------------------------
  1662. // CDragItemIterator::NextDragItem
  1663. //----------------------------------------------------------------------------------------
  1664. #pragma segment IteratorRes
  1665.  
  1666. TDragItem* CDragItemIterator::NextDragItem()
  1667. {
  1668.     this->Advance();
  1669.     if (this->More())
  1670.         return (TDragItem *)((TDragItemList *)fDynamicArray)->At(fCurrentIndex);
  1671.     else
  1672.         return NULL;
  1673. } // CDragItemIterator::NextDragItem
  1674.  
  1675. //========================================================================================
  1676. // CLASS TInvalCursorCommand
  1677. //========================================================================================
  1678. #undef Inherited
  1679. #define Inherited TCommand
  1680.  
  1681. #pragma segment MACommandNonRes
  1682. MA_DEFINE_CLASS_M1(TInvalCursorCommand, Inherited);
  1683.  
  1684. //----------------------------------------------------------------------------------------
  1685. // TInvalCursorCommand::TInvalCursorCommand
  1686. //----------------------------------------------------------------------------------------
  1687. #pragma segment MACommandRes
  1688.  
  1689. TInvalCursorCommand::TInvalCursorCommand()
  1690. {
  1691. }
  1692.  
  1693. //----------------------------------------------------------------------------------------
  1694. // TInvalCursorCommand::IInvalCursorCommand
  1695. //----------------------------------------------------------------------------------------
  1696. #pragma segment MACommandRes
  1697.  
  1698. void TInvalCursorCommand::IInvalCursorCommand()
  1699. {
  1700.     this->ICommand(cNoCommand, NULL, kCantUndo, kDoesNotCauseChange, NULL);
  1701. }
  1702.  
  1703. //----------------------------------------------------------------------------------------
  1704. // TInvalCursorCommand::DoIt
  1705. //----------------------------------------------------------------------------------------
  1706. #pragma segment MACommandRes
  1707.  
  1708. void TInvalCursorCommand::DoIt()
  1709. {
  1710.         // Compute based on where the mouse is right now 
  1711.     CPoint globalMouse;
  1712.  
  1713.     GetMouse(globalMouse);
  1714.     LocalToGlobal(globalMouse);
  1715.     
  1716.     gDispatcher->UpdateAllWindows();    // necessary for calculation of visible regions
  1717.     gDispatcher->InvalidateMouseRegions();
  1718.     gDispatcher->TrackCursor(globalMouse);
  1719. }
  1720.  
  1721. #endif // qDrag
  1722.  
  1723. //----------------------------------------------------------------------------------------
  1724. // End of UDragDrop.cp
  1725.  
  1726. #pragma segment Inline
  1727.